Skip to content

Add temperature unit to climate and water_heater#1600

Merged
bdraco merged 7 commits intoesphome:mainfrom
jhenkens:add-temperature-unit
Apr 22, 2026
Merged

Add temperature unit to climate and water_heater#1600
bdraco merged 7 commits intoesphome:mainfrom
jhenkens:add-temperature-unit

Conversation

@jhenkens
Copy link
Copy Markdown
Contributor

What does this implement/fix?

Exposes temperature unit for climate and water_heater, with corresponding changes in home-assistant/core, aioesphome, esphome, and esphome-docs, to enable native Fahrenheit measurements on those entities. Usecase is to enable accurate temperature settings on a Fahrenheit hot tub, controlled via RS485-UART. Rather than round tripped from F -> C -> C, with various floating point errors and weirdnesses, this just makes it stay F the entire way and work much more reliably.

Tests still need to be added where appropriate - that's on the todo - but the code has been validated.

When esphome is updated, but core is not, as long as you do not set the temperature unit on a climate/water heater, everything works the same as it currently is. If you do set it, you will convert from F -> "F", as home assistant will think the incoming value from ESPHome is C, without reading the UOM. If ESPHome does not have F specified, it continues to default to C.

When HA is updated, but ESPHome is on an old version, it maintains legacy behavior of treating all climate/water_heaters as using C.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Code quality improvements to existing code or addition of tests
  • Other

Related issue or feature (if applicable):

  • fixes

Pull request in esphome (if applicable):

home-assistant/core#168261
#1586
esphome/esphome#15815
esphome/esphome-docs#6463

Checklist:

  • The code change is tested and works locally.
  • If api.proto was modified, a linked pull request has been made to esphome with the same changes.
  • Tests have been added to verify that the new code works (under tests/ folder).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@bdraco has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 54 minutes and 16 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 54 minutes and 16 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e6ea957-2055-421e-8ed9-e0b0dd236aef

📥 Commits

Reviewing files that changed from the base of the PR and between 83eb532 and 52616cc.

📒 Files selected for processing (2)
  • aioesphomeapi/model.py
  • tests/test_model.py

Walkthrough

Adds temperature unit support to climate and water heater entities by introducing a TemperatureUnit enum with Celsius, Fahrenheit, and Kelvin values in the protobuf definition and corresponding Python model layer, extending both entity types with optional temperature_unit fields for reporting supported temperature units.

Changes

Cohort / File(s) Summary
Temperature Unit Enum
aioesphomeapi/api.proto, aioesphomeapi/model.py
Added new TemperatureUnit enum with CELSIUS (0), FAHRENHEIT (1), and KELVIN (2) values in both proto and Python model layers.
Climate Entity Extensions
aioesphomeapi/api.proto, aioesphomeapi/model.py
Extended ListEntitiesClimateResponse proto message and ClimateInfo dataclass with optional temperature_unit field using converter pattern.
Water Heater Entity Extensions
aioesphomeapi/api.proto, aioesphomeapi/model.py
Extended ListEntitiesWaterHeaterResponse proto message and WaterHeaterInfo dataclass with optional temperature_unit field using converter pattern.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of exposing temperature units for climate and water_heater entities, use cases, compatibility considerations, and cross-repository coordination.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Add temperature unit to climate and water_heater' accurately describes the main change: adding a temperature_unit field to both ClimateInfo and WaterHeaterInfo entities, enabling native temperature unit support.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
aioesphomeapi/model.py (1)

742-745: Consider defaulting temperature_unit to TemperatureUnit.CELSIUS instead of None for consistency.

Every other APIIntEnum field in this module uses the proto zero-value as its default (e.g., entity_category=EntityCategory.NONE, state_class=SensorStateClass.NONE, mode=NumberMode.AUTO, port_type=SerialProxyPortType.TTL). Since protobuf will always deliver 0 (CELSIUS) on the wire when the sender leaves the field unset, from_pb will never actually produce None here — only from_dict with a missing key will. Using default=TemperatureUnit.CELSIUS would:

  • match the documented compatibility semantics ("unset ⇒ treated as Celsius"),
  • keep behavior identical between from_pb and from_dict({}),
  • stay consistent with the surrounding enum-field pattern.
Proposed change
-    temperature_unit: TemperatureUnit | None = converter_field(
-        default=None,
-        converter=TemperatureUnit.convert,
-    )
+    temperature_unit: TemperatureUnit | None = converter_field(
+        default=TemperatureUnit.CELSIUS,
+        converter=TemperatureUnit.convert,
+    )

(Applies to both ClimateInfo and WaterHeaterInfo.)

Also applies to: 1196-1199

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aioesphomeapi/model.py` around lines 742 - 745, Change the enum field default
for temperature_unit from None to TemperatureUnit.CELSIUS: update the
converter_field call for the temperature_unit attribute (used in ClimateInfo and
WaterHeaterInfo) to use default=TemperatureUnit.CELSIUS instead of default=None
so it matches other APIIntEnum defaults, aligns from_pb/from_dict behavior, and
preserves converter=TemperatureUnit.convert.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@aioesphomeapi/model.py`:
- Around line 742-745: Change the enum field default for temperature_unit from
None to TemperatureUnit.CELSIUS: update the converter_field call for the
temperature_unit attribute (used in ClimateInfo and WaterHeaterInfo) to use
default=TemperatureUnit.CELSIUS instead of default=None so it matches other
APIIntEnum defaults, aligns from_pb/from_dict behavior, and preserves
converter=TemperatureUnit.convert.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5e2e695e-4d59-44b3-9b95-ea8f85f18eb2

📥 Commits

Reviewing files that changed from the base of the PR and between c6ef4d6 and 83eb532.

📒 Files selected for processing (3)
  • aioesphomeapi/api.proto
  • aioesphomeapi/api_pb2.py
  • aioesphomeapi/model.py

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 22, 2026

Merging this PR will not alter performance

✅ 11 untouched benchmarks


Comparing jhenkens:add-temperature-unit (52616cc) with main (05da893)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (c6ef4d6) during the generation of this report, so 05da893 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (05da893) to head (52616cc).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1600   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           25        25           
  Lines         4002      4008    +6     
=========================================
+ Hits          4002      4008    +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread aioesphomeapi/model.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a temperature unit enum and surfaces it on climate and water_heater entity info messages/models, enabling clients (notably Home Assistant) to interpret and preserve Fahrenheit-native setpoints end-to-end.

Changes:

  • Introduces TemperatureUnit in the API model layer and exposes it via ClimateInfo.temperature_unit and WaterHeaterInfo.temperature_unit.
  • Extends api.proto to include the TemperatureUnit enum and adds temperature_unit fields to the relevant ListEntities*Response messages.
  • Regenerates api_pb2.py to reflect the updated protobuf schema.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
aioesphomeapi/model.py Adds TemperatureUnit enum and new temperature_unit fields to climate/water-heater info dataclasses.
aioesphomeapi/api.proto Defines TemperatureUnit and wires it into climate/water-heater entity info messages.
aioesphomeapi/api_pb2.py Regenerated protobuf bindings reflecting the schema changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread aioesphomeapi/model.py Outdated
Comment thread aioesphomeapi/api.proto
Comment thread tests/test_model.py Outdated
Comment thread tests/test_model.py Outdated
@bdraco bdraco added the minor label Apr 22, 2026
@bdraco bdraco changed the title Add temperature unit Add temperature unit to climate and water_heater Apr 22, 2026
@bdraco bdraco merged commit e1bc076 into esphome:main Apr 22, 2026
15 checks passed
@jhenkens jhenkens deleted the add-temperature-unit branch April 22, 2026 02:43
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants